/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 *
 */

import { CoreTask, Module, TaskDetails } from '@ohos/hvigor';
import { TaskCreation } from '@ohos/hvigor/src/base/internal/task/core/lazy-task-container.js';
import { TaskContainer } from '@ohos/hvigor/src/base/internal/task/interface/task-container-interface.js';

import { AbstractModulePlugin } from '../plugin/common/abstract-module-plugin.js';

import { computeDepends, computeHookTaskDepends, computeTaskDetailsWithTarget } from './manager/creation-util.js';
import { ModuleTaskService } from './service/module-task-service.js';
import { TargetTaskService } from './service/target-task-service.js';

export interface CreationConfiguration {
  declareTaskDetail(): TaskDetails;

  declareDepends(): string[];

  configure(): void;
}

export abstract class DefaultTaskCreator implements CreationConfiguration, TaskCreation {
  abstract configure: () => void;

  abstract afterConfigure: () => void;

  abstract finalConfigured: () => void;

  abstract declareDepends(): string[];

  abstract declareTaskDetail(): TaskDetails;

  abstract depends: string[];

  abstract dependsDefinedByUser: string[];

  abstract details: TaskDetails;

  abstract provider: () => CoreTask;
}

export interface TargetAwareTask {
  targetService: TargetTaskService;
}

export abstract class GlobalTaskCreator extends DefaultTaskCreator {
  protected plugin: AbstractModulePlugin;
  protected service: ModuleTaskService;
  protected isFa = false;

  depends: string[] = [];
  dependsDefinedByUser: string[] = [];
  details: TaskDetails = { name: 'UninitializedTask' };

  constructor(service: ModuleTaskService, plugin: AbstractModulePlugin, isFa?: boolean) {
    super();
    this.service = service;
    this.plugin = plugin;
    this.isFa = isFa === undefined ? this.isFa : isFa;
  }

  configure = () => {
    this.details = this.declareTaskDetail();
  };

  afterConfigure = () => {
    this.depends = computeHookTaskDepends(this.declareDepends(), this.plugin.getNeedExecTargetServiceList());
  };

  // 新增的hook，在建立任务depend最后阶段，仅用于加入用户自定义的postDependency任务，为了解决为了挂载postDependency任务而提前初始化任务的问题
  finalConfigured = () => {
    // 在这个依赖中加入用户自定义的任务
    this.dependsDefinedByUser.forEach(task => {
      this.depends.push(task);
    });
  };
}

export abstract class TargetTaskCreator extends DefaultTaskCreator implements TargetAwareTask {
  protected node: Module;
  protected isFa = false;
  protected isFastBuild = false;
  targetService: TargetTaskService;

  depends: string[] = [];

  dependsDefinedByUser: string[] = [];

  details: TaskDetails = { name: '' };

  constructor(service: TargetTaskService, isFa?: boolean) {
    super();
    this.targetService = service;
    this.node = this.targetService.getModuleService().getNode();
    this.isFa = isFa === undefined ? this.isFa : isFa;
    this.isFastBuild = service.getTargetData().getProduct()?.buildOption?.packOptions?.fastBuildApp || false;
  }

  configure = () => {
    this.details = computeTaskDetailsWithTarget(this.declareTaskDetail(), this.targetService);
  };

  afterConfigure = () => {
    this.depends = computeDepends(this.declareDepends(), this.targetService);
  };

  // 新增的hook，在建立任务depend最后阶段，仅用于加入用户自定义的postDependency任务，为了解决为了挂载postDependency任务而提前初始化任务的问题
  finalConfigured = () => {
    // 在这个依赖中加入用户自定义的任务
    this.dependsDefinedByUser.forEach(task => {
      this.depends.push(task);
    });
  };
}

export class TaskCreatorManager {
  private readonly _taskContainer: TaskContainer;
  private readonly _creators: DefaultTaskCreator[] = [];

  getTaskContainer(): TaskContainer {
    return this._taskContainer;
  }

  constructor(taskContainer: TaskContainer) {
    this._taskContainer = taskContainer;
  }

  registry(creator: DefaultTaskCreator) {
    creator.configure();
    this._creators.push(creator);
    this._taskContainer.registerTask(creator);
  }

  configure() {
    this._creators.forEach((creator) => {
      creator.afterConfigure();
      creator.finalConfigured();
    });
  }
}
